home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cmouse.zip / CMOUSE.CPP < prev    next >
C/C++ Source or Header  |  1991-04-02  |  15KB  |  600 lines

  1. /*
  2.  
  3.     cmouse.cpp
  4.     4-2-90
  5.     Microsoft mouse interrupt functions
  6.  
  7.     Copyright 1991
  8.     John W. Small
  9.     All rights reserved
  10.  
  11.     PSW / Power SoftWare
  12.     P.O. Box 10072
  13.     McLean, Virginia 22102 8072
  14.     (703) 759-3838
  15.  
  16.  
  17.     Works consulted:
  18.  
  19.     "Microsoft Mouse Programmer's Reference."
  20.         Bellevue, Washington: Microsoft Press, 1989.
  21.  
  22.     "Microsoft Mouse Programmer's Reference Guide."
  23.         Bellevue, Washington: Microsoft Press, 1986.
  24.  
  25.     Refer to above works for mouse function
  26.     documentation.
  27.  
  28. */
  29.  
  30.  
  31. #include <dos.h>    /* union REGS, struct SREGS, */
  32.             /*  int86(), int86x(), */
  33.             /* geninterrupt(), enable() */
  34. #include <cmouse.hpp>
  35.  
  36. MicrosoftMouse MM;    // Only instance allowed!
  37.  
  38. unsigned MicrosoftMouse::Xcell[] = {
  39.     16,16,8,8,2,2,1,8,1,1,1,1,1,2,1,1,1,1,1,2};
  40. unsigned MicrosoftMouse::Ycell[] = {
  41.     8,8,8,8,1,1,1,8,1,1,1,1,1,1,1,1,1,1,1,1};
  42. unsigned MicrosoftMouse::LeftTopOfs[] = {
  43.     1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0};
  44.  
  45. MicrosoftMouse::~MicrosoftMouse()
  46. {
  47.     on();
  48.     restore();
  49.     clearAltInterrupts();
  50.     reset();
  51.     state = origState;
  52.     restore();
  53. }
  54.  
  55. /* Stack overflow check overwrites AX : do not compile with -N */
  56. /* Do not call!  Use to cookbook your own if needed. */
  57. #pragma argsused
  58. void interrupt MMautoEventHandler(
  59.     unsigned iBP,
  60.     unsigned vertMickeys,    /* di */
  61.     unsigned horzMickeys,    /* si */
  62.     unsigned iDS,
  63.     unsigned iES,
  64.     unsigned y,              /* dx */
  65.     unsigned x,              /* cx */
  66.     unsigned buttonState,    /* bx */
  67.     unsigned conditionMask,  /* ax */
  68.     unsigned iIP,
  69.     unsigned iCS,
  70.     unsigned pseudoFlags)     /* not present */
  71. {
  72.     MM.eventTime = (*(long far *)MK_FP(0x0040,0x006C));
  73.     enable();
  74.  
  75.     MM.eventCount++;
  76.     MM.eventFlags = conditionMask;
  77.     MM.leftPressed = (buttonState & MBleft)? 1 : 0;
  78.     MM.rightPressed = (buttonState & MBright)? 1 : 0;
  79.     MM.x = MM.physicalX(x);
  80.     MM.y = MM.physicalY(y);
  81.     MM.horzMickeys = horzMickeys;
  82.     MM.vertMickeys = vertMickeys;
  83.  
  84.     if (conditionMask & MEmoved)
  85.         MM.eventMoved++;
  86.     if (conditionMask & MEleftPressed)  {
  87.         MM.leftPressed = 1;
  88.         MM.lastLeftPressX = MM.x;
  89.         MM.lastLeftPressY = MM.y;
  90.         MM.leftPresses++;
  91.         MM.buttonRequested = MBleft;
  92.         if ((MM.leftClickTime > MM.eventTime) ||
  93.             ((MM.eventTime - MM.leftClickTime)
  94.             > MM.clickTimeOut))  {
  95.             MM.leftClickTime = MM.eventTime;
  96.             MM.leftClicks = 0;
  97.         }
  98.     }
  99.     if (conditionMask & MEleftReleased)  {
  100.         MM.leftPressed = 0;
  101.         MM.lastLeftReleaseX = MM.x;
  102.         MM.lastLeftReleaseY = MM.y;
  103.         MM.leftReleases++;
  104.         MM.buttonRequested = MBleft;
  105.         if ((MM.leftClickTime > MM.eventTime) ||
  106.             ((MM.eventTime - MM.leftClickTime)
  107.             > MM.clickTimeOut))  {
  108.             MM.leftClickTime = MM.eventTime;
  109.             MM.leftClicks = 0;
  110.         }
  111.         else
  112.             MM.leftClicks++;
  113.     }
  114.     if (conditionMask & MErightPressed)  {
  115.         MM.rightPressed = 1;
  116.         MM.lastRightPressX = MM.x;
  117.         MM.lastRightPressY = MM.y;
  118.         MM.rightPresses++;
  119.         MM.buttonRequested = MBright;
  120.         if ((MM.rightClickTime > MM.eventTime) ||
  121.             ((MM.eventTime - MM.rightClickTime)
  122.             > MM.clickTimeOut))  {
  123.             MM.rightClickTime = MM.eventTime;
  124.             MM.rightClicks = 0;
  125.         }
  126.     }
  127.     if (conditionMask & MErightReleased)  {
  128.         MM.rightPressed = 0;
  129.         MM.lastRightReleaseX = MM.x;
  130.         MM.lastRightReleaseY = MM.y;
  131.         MM.rightReleases++;
  132.         MM.buttonRequested = MBright;
  133.         if ((MM.rightClickTime > MM.eventTime) ||
  134.             ((MM.eventTime - MM.rightClickTime)
  135.             > MM.clickTimeOut))  {
  136.             MM.rightClickTime = MM.eventTime;
  137.             MM.rightClicks = 0;
  138.         }
  139.         else
  140.             MM.rightClicks++;
  141.     }
  142.  
  143. /*
  144.     Convert from Interrupt stack frame to FAR call stack
  145.     frame then return from FAR.  Since the mouse driver
  146.     FAR calls this interrupt handler instead of issuing
  147.     an interrupt call to get here, this event handler
  148.     needs to return from a FAR call instead of returning
  149.     from an interrupt!  A Turbo C++    interrupt function
  150.     was used since it automatically restores DS to the
  151.     data segment.  The mouse driver also passes
  152.     parameters in registers instead of on the
  153.     stack.  TC++'s interrupt keyword forces the function
  154.     to automatically stack these registers so that they
  155.     can be accessed.
  156. */
  157.  
  158.     asm mov ax,iDS       /* restore DS */
  159.     asm mov ds,ax
  160.  
  161.     conditionMask = iBP; /* skip over parameters */
  162.     asm add bp,OFFSET conditionMask
  163.  
  164.     asm mov sp,bp        /* exit far proc */
  165.     asm pop bp
  166.     asm retf
  167. }
  168.  
  169. MicrosoftMouse::MicrosoftMouse()
  170. {
  171.     unsigned char far *vec;
  172.  
  173.     vmode = 0;
  174.     present = 0;
  175.     buttons = 0;
  176.     leftPressed = 0; rightPressed = 0;
  177.     x = 0; y = 0;
  178.     lastLeftPressX = 0; lastLeftPressY = 0;
  179.     leftPresses = 0;
  180.     buttonRequested = MBleft;
  181.     lastLeftReleaseX = 0; lastLeftReleaseY = 0;
  182.     leftReleases = 0;
  183.     lastRightPressX = 0; lastRightPressY = 0;
  184.     rightPresses = 0;
  185.     lastRightReleaseX = 0; lastRightReleaseY = 0;
  186.     rightReleases = 0;
  187.     vertMickeys= 0; horzMickeys = 0;
  188.     handler = (MouseHandler) 0;
  189.     callMask = 0;
  190.     eventMask = 0x001F;
  191.     eventFlags = 0;
  192.     eventCount = 0;
  193.     eventMoved = 0;
  194.     eventTime = 0;
  195.     clickTimeOut = 10;
  196.     leftClickTime = 0;
  197.     leftClicks = 0;
  198.     rightClickTime = 0;
  199.     rightClicks = 0;
  200.     origState = (void *) 0;
  201.     state = (void *) 0;
  202.     stateSize = 0;
  203.     altHandler = (MouseHandler) 0;
  204.     altCallMask = 0;
  205.     horzPercent = 50; vertPercent = 50;
  206.     doublePercent = 50;
  207.     crtPage = 0;
  208.     mouseIntrVector = (MouseDriver) 0;
  209.     language = MLenglish;
  210.     driverVersion = 0;
  211.     IRQ = -1;
  212.     typeRequired = MTunknown;
  213.     vec = (unsigned char far *) getvect(MOUSE_INT);
  214.     if (!vec || (*vec == 0xCF)) /* IRET */
  215.         return;
  216.     reset();
  217.     driver();
  218.     if (!present)
  219.         return;
  220.     save();
  221.     origState = state;
  222.     state = (void *) 0;
  223. }
  224.  
  225. void MicrosoftMouse::reset()            /* MF0 */
  226. {
  227.     _AH = 0x0F;
  228.     geninterrupt(0x10);
  229.     vmode = _AL;
  230.     _AX = 0;
  231.     geninterrupt(MOUSE_INT);
  232.     if (_AX) {
  233.         buttons = _BX;
  234.         present = 1;
  235.     }
  236.     else
  237.         buttons = present = 0;
  238. }
  239.  
  240. void MicrosoftMouse::updateStatusInfo()        /* MF3 */
  241. {
  242.     unsigned buttons;
  243.  
  244.     _AX = 3;
  245.     geninterrupt(MOUSE_INT);
  246.     buttons = _BX;
  247.     x = _CX;
  248.     y = _DX;
  249.     leftPressed = (buttons & MBleft)? 1 : 0;
  250.     rightPressed = (buttons & MBright)? 1 : 0;
  251.     x = physicalX(x);
  252.     y = physicalY(y);
  253. }
  254.  
  255. void MicrosoftMouse::gotoxy()            /* MF4 */
  256. {
  257.     unsigned vx, vy;
  258.  
  259.     vx = virtualX(x);
  260.     vy = virtualY(y);
  261.     _CX = vx;
  262.     _DX = vy;
  263.     _AX = 4;
  264.     geninterrupt(MOUSE_INT);
  265. }
  266.  
  267. void MicrosoftMouse::updatePressInfo()        /* MF5 */
  268. {
  269.     union REGS rgs;
  270.  
  271.     rgs.x.ax = 5;
  272.     rgs.x.bx = buttonRequested >> 1;
  273.     (void) int86(MOUSE_INT,&rgs,&rgs);
  274.     leftPressed = (rgs.x.ax & MBleft)? 1 : 0;
  275.     rightPressed = (rgs.x.ax & MBright)? 1 : 0;
  276.     if (buttonRequested == MBleft)  {
  277.         leftPresses = rgs.x.bx;
  278.         lastLeftPressX = physicalX(rgs.x.cx);
  279.         lastLeftPressY = physicalY(rgs.x.dx);
  280.     }
  281.     else {
  282.         rightPresses = rgs.x.bx;
  283.         lastRightPressX = physicalX(rgs.x.cx);
  284.         lastRightPressY = physicalY(rgs.x.dx);
  285.     }
  286. }
  287.  
  288. void MicrosoftMouse::updateReleaseInfo()    /* MF6 */
  289. {
  290.     union REGS rgs;
  291.  
  292.     rgs.x.ax = 6;
  293.     rgs.x.bx = buttonRequested >> 1;
  294.     (void) int86(MOUSE_INT,&rgs,&rgs);
  295.     leftPressed = (rgs.x.ax & MBleft)? 1 : 0;
  296.     rightPressed = (rgs.x.ax & MBright)? 1 : 0;
  297.     if (buttonRequested == MBleft)  {
  298.         leftReleases = rgs.x.bx;
  299.         lastLeftReleaseX = physicalX(rgs.x.cx);
  300.         lastLeftReleaseY = physicalY(rgs.x.dx);
  301.     }
  302.     else {
  303.         rightReleases = rgs.x.bx;
  304.         lastRightReleaseX = physicalX(rgs.x.cx);
  305.         lastRightReleaseY = physicalY(rgs.x.dx);
  306.     }
  307. }
  308.  
  309. void MicrosoftMouse::trap(unsigned x1, unsigned y1,
  310.     unsigned x2, unsigned y2)
  311. {                        /* MF7, MF8 */
  312.     unsigned d1, d2;
  313.  
  314.     d1 = virtualX(x1);
  315.     d2 = virtualX(x2);
  316.     _CX = d1;
  317.     _DX = d2;
  318.     _AX = 7;
  319.     geninterrupt(MOUSE_INT);
  320.     d1 = virtualY(y1);
  321.     d2 = virtualY(y2);
  322.     _CX = d1;
  323.     _DX = d2;
  324.     _AX = 8;
  325.     geninterrupt(MOUSE_INT);
  326. }
  327.  
  328. void MicrosoftMouse::graphicsCursor(signed char horzHS,
  329.     signed char vertHS,
  330.     unsigned far *scrCurMask)               /* MF9 */
  331. {
  332.     unsigned h, v;
  333.  
  334.     h = ((unsigned) horzHS) * Xcell[vmode];
  335.     v = ((unsigned) vertHS) * Ycell[vmode];
  336.     _ES = FP_SEG(scrCurMask);
  337.     _DX = FP_OFF(scrCurMask);
  338.     _BX = h;
  339.     _CX = v;
  340.     _AX = 9;
  341.     geninterrupt(MOUSE_INT);
  342. }
  343.  
  344. void MicrosoftMouse::swapInterrupts()        /* MF20 */
  345. {
  346.     union REGS rgs;
  347.     struct SREGS srgs;
  348.  
  349.     rgs.x.ax = 20;
  350.     rgs.x.cx = callMask;
  351.     rgs.x.dx = FP_OFF(handler);
  352.     srgs.es = FP_SEG(handler);
  353.     (void) int86x(MOUSE_INT,&rgs,&rgs,&srgs);
  354.     callMask = rgs.x.cx;
  355.     handler = (MouseHandler) MK_FP(srgs.es,rgs.x.dx);
  356. }
  357.  
  358. void MicrosoftMouse::autoEventUpdate()        /* N/A  */
  359. {
  360.     handler = (MouseHandler) MMautoEventHandler;
  361.     callMask = eventMask;
  362.     swapInterrupts();
  363. }
  364.  
  365. void MicrosoftMouse::save()            /* MF21, MF22 */
  366. {
  367.     union REGS rgs;
  368.     struct SREGS srgs;
  369.  
  370.     if (state) return;
  371.     _AX = 21;
  372.     geninterrupt(MOUSE_INT);
  373.     stateSize = _BX;
  374.     if ((state = (void *) new char [stateSize])
  375.         == (void *) 0) return;
  376.     srgs.es = FP_SEG((void far *)state);
  377.     rgs.x.dx = FP_OFF((void far *)state);
  378.     rgs.x.ax = 22;
  379.     (void) int86x(MOUSE_INT,&rgs,&rgs,&srgs);
  380. }
  381.  
  382. void MicrosoftMouse::restore()            /* MF23 */
  383. {
  384.     union REGS rgs;
  385.     struct SREGS srgs;
  386.  
  387.     if(!state) return;
  388.     srgs.es = FP_SEG((void far *)state);
  389.     rgs.x.dx = FP_OFF((void far *)state);
  390.     rgs.x.ax = 23;
  391.     (void) int86x(MOUSE_INT,&rgs,&rgs,&srgs);
  392.     delete state;
  393.     state = (void *) 0;
  394. }
  395.  
  396. void MicrosoftMouse::clearAltInterrupts()    /* N/A  */
  397. {
  398.     altHandler = (MouseHandler) 0;
  399.     altCallMask = MEshiftPressed
  400.         | MEctrlPressed | MEaltPressed;
  401.     setAltInterrupt();
  402.     altCallMask = MEshiftPressed | MEctrlPressed;
  403.     setAltInterrupt();
  404.     altCallMask = MEshiftPressed | MEaltPressed;
  405.     setAltInterrupt();
  406.     altCallMask = MEctrlPressed | MEaltPressed;
  407.     setAltInterrupt();
  408.     altCallMask = MEshiftPressed;
  409.     setAltInterrupt();
  410.     altCallMask = MEctrlPressed;
  411.     setAltInterrupt();
  412.     altCallMask = MEaltPressed;
  413.     setAltInterrupt();
  414. }
  415.  
  416. void MicrosoftMouse::off()            /* MF31 */
  417. {
  418.     union REGS rgs;
  419.     struct SREGS srgs;
  420.  
  421.     if (mouseIntrVector) return;
  422.     rgs.x.ax = 31;
  423.     (void) int86x(MOUSE_INT,&rgs,&rgs,&srgs);
  424.     if (rgs.x.ax == 0xFFFF) return;
  425.     mouseIntrVector = getvect(MOUSE_INT);
  426.     setvect(MOUSE_INT, (MouseDriver)
  427.         MK_FP(srgs.es,rgs.x.bx));
  428. }
  429.  
  430. void MicrosoftMouse::on()            /* MF32 */
  431. {
  432.     if (!mouseIntrVector) return;
  433.     setvect(MOUSE_INT, mouseIntrVector);
  434.     mouseIntrVector = (MouseDriver) 0;
  435.     _AX = 32;
  436.     geninterrupt(MOUSE_INT);
  437. }
  438.  
  439. void MicrosoftMouse::softReset()        /* MF33 */
  440. {
  441.     _AX = 0x0F00;
  442.     geninterrupt(0x10);
  443.     vmode = _AL;
  444.     _AX = 33;
  445.     geninterrupt(MOUSE_INT);
  446.     present = ((_AX == 0xFFFF) && (_BX == 2))? 1 : 0;
  447. }
  448.  
  449. void MicrosoftMouse::driver()            /* MF36 */
  450. {
  451.     union REGS rgs;
  452.  
  453.     rgs.x.ax = 36;
  454.     (void) int86(MOUSE_INT,&rgs,&rgs);
  455.     driverVersion = rgs.x.bx;
  456.     IRQ = rgs.h.cl;
  457.     typeRequired = rgs.h.ch;
  458. }
  459.  
  460.  
  461. // To use cmouse in your application
  462. // comment out //#define TEST_CMOUSE_CPP
  463. #define TEST_CMOUSE_CPP
  464. #ifdef TEST_CMOUSE_CPP
  465.  
  466. #include <conio.h>    /* clrscr(), gotoxy(), cprintf() */
  467. #include <stdlib.h>
  468. #include <graphics.h>
  469.  
  470. char *mice[] = {
  471.     "Unknown", "Bus", "Serial",
  472.     "InPort", "PS2", "HP"
  473. };
  474.  
  475. void MouseReport()
  476. {
  477.     (void) cprintf("\r\nMouse Driver Version : %d.%d%d",
  478.         MM.driverVersion >> 8,
  479.         (MM.driverVersion & 0x00F0) >> 4,
  480.         (MM.driverVersion & 0x000F));
  481.     (void) cprintf("\r\nRequires : %s Mouse",mice[MM.typeRequired]);
  482.     if (MM.present)
  483.         (void) cprintf("\r\nMouse has %2d buttons.",MM.buttons);
  484.     else
  485.         (void) cprintf("\r\nMouse not connected!");
  486.     (void) cprintf("\r\n\nMouse cursor @ (%3d,%3d)",MM.x,MM.y);
  487.     (void) cprintf("    Left  : %s",MM.leftPressed? "Down":"Up  ");
  488.     (void) cprintf("    Right : %s",MM.rightPressed? "Down":"Up  ");
  489.     (void) cprintf("\r\n%s button requested",
  490.         (MM.buttonRequested == MBleft)?
  491.         "Left " : "Right");
  492.     (void) cprintf("\r\nLeft:   Presses  : %3d  @ (%3d,%3d)   ",
  493.         MM.leftPresses, MM.lastLeftPressX,
  494.         MM.lastLeftPressY);
  495.     (void) cprintf("Releases : %3d  @ (%3d,%3d)",
  496.         MM.leftReleases, MM.lastLeftReleaseX,
  497.         MM.lastLeftReleaseY);
  498.     (void) cprintf("\r\nRight:  Presses  : %3d  @ (%3d,%3d)   ",
  499.         MM.rightPresses, MM.lastRightPressX,
  500.         MM.lastRightPressY);
  501.     (void) cprintf("Releases : %3d  @ (%3d,%3d)",
  502.         MM.rightReleases, MM.lastRightReleaseX,
  503.         MM.lastRightReleaseY);
  504.     (void) cprintf("\r\nMickeys :  Horz  : %10u   Vert  : %10u",
  505.         MM.horzMickeys, MM.vertMickeys);
  506.     (void) cprintf("\r\nEvent   :  Count : %10u   Time  : %10lu   Flags : %10u",
  507.         MM.eventCount, MM.eventTime, MM.eventFlags);
  508.     (void) cprintf("\r\nClicks  :  Left  : %10u   Right : %10u",
  509.         MM.leftClicks, MM.rightClicks);
  510.     (void) cprintf("\r\n@ time  :  Left  : %10lu   Right : %10lu",
  511.         MM.leftClickTime, MM.rightClickTime);
  512. }
  513.  
  514. main()
  515. {
  516.     unsigned ec;
  517.     int gdriver, gmode, gerror;
  518.     int dx, c;
  519.  
  520.     clrscr();
  521.     gotoxy(10,20);
  522.     cprintf("Press any key to continue ...");
  523.     MM.show();
  524.     MM.autoEventUpdate();
  525.     ec = MM.eventCount;
  526.     MM.condOffZone(1,2,71,13);
  527.     while (!kbhit())  {
  528.         gotoxy(1,1);
  529.         MM.condOff();
  530.         MouseReport();
  531.         MM.show();
  532.         while ((ec == MM.eventCount) && !kbhit());
  533.         ec = MM.eventCount;
  534.     }
  535.     getch();  // clear keyboard buffer
  536.  
  537.     gdriver = DETECT;
  538.     initgraph(&gdriver, &gmode, "\\borlandc\\bgi");
  539.     gerror = graphresult();
  540.     if (gerror != grOk)  /* an error occurred */
  541.     {
  542.        clrscr();
  543.        cprintf("Not able to demo in graphics mode: %s",
  544.         grapherrormsg(gerror));
  545.        cprintf("\r\nPress any key to halt:");
  546.        getch();
  547.        exit(1);
  548.     }
  549.     MM.reset();  // call after any video mode change.
  550.     directvideo = 0;  // enable conio i/o in graphics mode
  551.  
  552.     dx = getmaxx() / (getmaxcolor()+1);
  553.     clearviewport();
  554.     for (c = 0; c <= getmaxcolor(); c++)  {
  555.         setfillstyle(XHATCH_FILL,c);
  556.         bar3d(c*dx,0,(c+1)*dx,getmaxy(),0,0);
  557.     }
  558.  
  559.     gotoxy(10,20);
  560.     cprintf("Press any key to quit ...");
  561.  
  562.     MM.show();
  563.     MM.autoEventUpdate();
  564.     ec = MM.eventCount;
  565.     MM.condOffZone(0,0,570,208);
  566.     while (!kbhit())  {
  567.         gotoxy(1,1);  // conio remember!
  568.         MouseReport();
  569.         // CondOff() really belongs before MouseReport
  570.         // because conio is so slow I put it here.
  571.         // If you XOR_PUT to screen make sure mouse is
  572.         // hidden by condOff() or hide() before updating!
  573.         MM.condOff();
  574.         MM.show();
  575.         while ((ec == MM.eventCount) && !kbhit());
  576.         ec = MM.eventCount;
  577.     }
  578.  
  579.     closegraph();
  580.     cputs("If you find cmouse useful and are using it in your");
  581.     cputs("\r\napplications, how about telling a friend about it.");
  582.     cputs("\r\nCmouse is freeware - I only ask that you leave my");
  583.     cputs("\r\ncopyright notice untouched!  I will try to answer");
  584.     cputs("\r\nas many of your questions and/or comments (time ");
  585.     cputs("\r\nand money permitting).  Thanks!  John CIS: 73757,2233");
  586.     cputs("\r\n");
  587.     cputs("\r\nPSW / Power SoftWare");
  588.     cputs("\r\nP.O. Box 10072");
  589.     cputs("\r\nMcLean, Virginia 22102 8072");
  590.     cputs("\r\n(703) 759-3838");
  591.     cputs("\r\n");
  592.     cputs("\r\nThat's all folks!");
  593.     cputs("\r\n");
  594.     cputs("\r\nPress enter to quit.");
  595.     getch();
  596.  
  597.     return 0;
  598. }
  599.  
  600. #endif